using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using DZTC.UselessAppEver.Base32.Exceptions;
using DZTC.UselessAppEver.Core;
using DZTC.UselessAppEver;

namespace DZTC.UselessAppEver.UI
{
    

    public class ConversionController
    {
        public ConversionForm View { get; private set; }

        private CancellationTokenSource ConversionCancellation { get; set; }
        private ProgressToken ConversionProgress { get; set; }
        private Thread ConversionThread { get; set; }

        private string InputFile { get; set; }
        private string OutputFile { get; set; }

        private IConversionOperation Operation { get; set; }

        private SynchronizationContext SynchronizationContext { get; set; }

        private void ConversionThreadEntry()
        {
            var rollback = false;

            try
            {
                using (var inputFileStream = File.Open(InputFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (var outputFileStream = File.Open(OutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    Operation.PerformConversion(inputFileStream,
                                                outputFileStream,
                                                ConversionCancellation.Token,
                                                ConversionProgress);


                }
            }
            catch (OperationCanceledException ex)
            {
                rollback = true;
            }
            catch (IOException ex)
            {
                Dialog.IOError(ex.Message);
                rollback = true;
            }
            catch (Base32Exception ex)
            {
                Dialog.Base32Error(ex.Message);
                rollback = true;
            }

            if (rollback)
            {
                FileHelpers.TryDeleteFile(OutputFile);
            }

            View.Invoke(v => v.CloseForm());
        }

        private void ProgressChanged(int value, int delta)
        {
            View.Invoke(v => v.UpdateProgress(value));
        }

        public void Start()
        {
            if (ConversionThread != null)
                throw new InvalidOperationException("Already started");

            //SynchronizationContext = SynchronizationContext.Current;
            
            ConversionCancellation = new CancellationTokenSource();
            ConversionProgress = new ProgressToken();
            ConversionProgress.ProgressChanged +=ProgressChanged;

            ConversionThread = new Thread(ConversionThreadEntry);
            ConversionThread.Start();
        }

        public void Cancel(bool formClose)
        {
            if (ConversionThread == null)
                throw new InvalidOperationException("Not started");

            ConversionCancellation.Cancel();

        }

        public ConversionController(string inputFile, string outputFile, IConversionOperation operation)
        {
            InputFile = inputFile;
            OutputFile = outputFile;
            Operation = operation;
        
            View = new ConversionForm(this);
            View.SetFileNames(Path.GetFileName(InputFile), Path.GetFileName(OutputFile));
        }

        public void RunConversion()
        {
            //Start();
            View.ShowDialog();
        }
    }
}